﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Code.Models;
using log4net;
using Code.DAL;
using System.Linq.Expressions;

namespace Code.BLL
{
    public class ManageBase<TableName> where TableName:class
    {
        public ManageBase()
        {
            Table = new Table<TableName>();
        }
        private Table<TableName> Table { get; set; }

        protected DBContext Tables { get { return Table.DB; } }

        /// <summary>
        /// 检查连接是否正常
        /// </summary>
        /// <returns></returns>
        public bool CheckConnection()
        {
            return Table.CheckConnection();
        }
        /// <summary> 
        /// 获取数据库的时间
        /// </summary>
        /// <returns></returns>
        protected DateTime? GetServerDate()
        {
            return DateTime.Now;
        }
        /// <summary>
        /// 获取当前用户的下级
        /// </summary>
        /// <param name="uid"></param>
        /// <param name="sub">是否需要获取所有下级</param>
        /// <returns></returns>
        public IQueryable<GetChidsResult> GetUserChilds(Guid uid)
        {
            return this.Tables.GetChids(uid);
        }

        /// <summary>
        /// 获取下级的ID和下级所对应的上级ID(包括自己)
        /// </summary>
        /// <param name="uid"></param>
        /// <param name="sub">是否包括所有下级</param>
        /// <returns></returns>
        public IEnumerable<GetChidsResult> GetUserChild_ContainMe(Guid uid)
        {
            return this.Table.Select<Users,IEnumerable<GetChidsResult>>(s => s.Where(p => p.Commands.Contains(p.ID.ToString()) || p.ID == uid).Select(p => new GetChidsResult { ID = p.ID, CommandID = p.CommandID }));
        }
        /// <summary>
        /// 更新由 TableName  指定的表
        /// </summary>
        /// <param name="delWhere">删除的条件,类的属性名要和表的列名一致 无条件则为 null</param>
        /// <exception cref="System.ArgumentOutOfRangeException" />
        /// <returns>删除的行数</returns>
        public virtual int Delete(params object[] delWhere)
        {
            return Delete<TableName>(delWhere);
        }
        /// <summary>
        /// 更新由 TableName  指定的表
        /// </summary>
        /// <param name="delWhere">删除的条件,类的属性名要和表的列名一致 无条件则为 null</param>
        /// <exception cref="System.ArgumentOutOfRangeException" />
        /// <returns>删除的行数</returns>
        //protected int Delete<TableName>(IEnumerable<object> delWhere)
        //{
        //    return this.Delete<TableName>(delWhere.ToArray());
        //}
        /// <summary>
        /// 更新由 Table 指定的表
        /// </summary>
        /// <param name="delWhere">删除的条件,类的属性名要和表的列名一致 无条件则为 null</param>
        /// <exception cref="System.ArgumentOutOfRangeException" />
        /// <returns>删除的行数</returns>
        public virtual int Delete<Table>(params object[] delWhere)
        {
            return this.Table.Delete<Table>(delWhere);
        }

        /// <summary>
        /// 删除 TableName  指定的表 的数据
        /// </summary>
        /// <param name="expression">删除的条件</param>
        /// <returns>删除的行数</returns>
        protected int Delete(Expression<Func<IQueryable<TableName>, IQueryable<object>>> expression)
        {
            return this.Table.Delete<object>(expression);
        }

        /// <summary>
        /// 删除 Table  指定的表 的数据
        /// </summary>
        /// <param name="expression">删除的条件</param>
        /// <returns>删除的行数</returns>
        protected int Delete<Del,Table>(Expression<Func<IQueryable<Table>, IEnumerable<object>>> expression) where Table : class
        {
            return this.Table.Delete<Del,Table>(expression);
        }

        public virtual int Execute(SqlExpression expression)
        {
            return this.Table.ExecuteExpression(expression);
        }

        /// <summary>
        /// 新增由 TableName 指定的表
        /// </summary>
        /// <param name="insertItem">新增的集合,类的属性名要和表的列名一致</param>
        /// <exception cref="System.ArgumentOutOfRangeException" />
        /// <returns>成功的行数</returns>
        public virtual int Insert(params object[] insertItem)
        {
            return Insert<TableName>(insertItem);
        }

        /// <summary>
        /// 新增由 Table 指定的表
        /// </summary>
        /// <param name="insertItem">新增的集合,类的属性名要和表的列名一致</param>
        /// <exception cref="System.ArgumentOutOfRangeException" />
        /// <returns></returns>
        public virtual int Insert<Table>(params object[] insertItem)
        {
            return this.Table.Insert<Table>(insertItem);
        }

        #region select
        /// <summary>
        /// 查询由 TableName 指定的表
        /// </summary>
        /// <param name="expression">查询表达式</param>
        /// <exception cref="System.ArgumentNullException" />
        public virtual TResult Select<TResult>(Expression<Func<IQueryable<TableName>, TResult>> expression)
        {
            return Select<TableName, TResult>(expression);

        }

        /// <summary>
        /// 查询由 Table 指定的表
        /// </summary>
        /// <exception cref="System.ArgumentNullException" />
        /// <param name="expression">查询表达式</param>
        public virtual TResult Select<Table, TResult>(Expression<Func<IQueryable<Table>, TResult>> expression) where Table : class
        {
            return this.Table.Select<Table, TResult>(expression);
        }

        #endregion

        /// <summary>
        /// 更新由 TableName  指定的表的数据
        /// </summary>
        /// <param name="update">要更新的属性,类的属性名要和表的列名一致</param>
        /// <param name="where">做为筛选的条件,类的属性名要和表的列名一致 无条件则为 null</param>
        /// <exception cref="System.ArgumentOutOfRangeException" />
        /// <returns>更新的行数</returns>
        public  virtual int Update(object update, object where)
        {
            return Update<TableName>(new NameValue<object, object>() { { update, where } });
        }

        /// <summary>
        /// 更新由 Table 指定的表的数据
        /// </summary>
        /// <param name="update">要更新的属性,类的属性名要和表的列名一致</param>
        /// <param name="where">做为筛选的条件,类的属性名要和表的列名一致 无条件则为 null</param>
        /// <exception cref="System.ArgumentOutOfRangeException" />
        /// <returns>更新的行数</returns>
        public virtual int Update<Table>(object update, object where)
        {
            return Update<Table>(new NameValue<object, object>() { { update, where } });
        }

        /// <summary>
        /// 更新由 Table  指定的表的数据
        /// </summary>
        /// <param name="updateItem">由键值队组成的集合，每一个键值队代表一个更新操作，
        /// Key为要更新的内容,类的属性名要和表的列名一致
        /// Value做为 Where 条件的类,类的属性名要和表的列名一致 无条件则为 null，
        /// </param>
        /// <exception cref="System.ArgumentOutOfRangeException" />
        /// <returns>更新的行数</returns>
        public virtual int Update<Table>(NameValue<object, object> updateItem)
        {
            return this.Table.Update<Table>(updateItem);
        }

        /// <summary>
        /// 更新由 Table  指定的表的数据
        /// </summary>
        /// <param name="updateItem">由键值队组成的集合，每一个键值队代表一个更新操作，
        /// Key为要更新的内容,类的属性名要和表的列名一致
        /// Value做为 Where 条件的类,类的属性名要和表的列名一致 无条件则为 null，
        /// </param>
        /// <exception cref="System.ArgumentOutOfRangeException" />
        /// <returns>更新的行数</returns>
        public virtual int Update(NameValue<object, object> updateItem)
        {
            return this.Table.Update(updateItem);
        }

        /// <summary>
        /// 更新由 TableName  指定的表的数据
        /// </summary>
        /// <param name="updateItem">由键值队组成的集合，每一个键值队代表一个更新操作，
        /// Key为要更新的内容,类的属性名要和表的列名一致
        /// Value做为 Where 条件的类,类的属性名要和表的列名一致 无条件则为 null，
        /// </param>
        /// <exception cref="System.ArgumentOutOfRangeException" />
        /// <returns>更新的行数</returns>
        //protected virtual int Update(IDictionary<object, object> updateItem)
        //{
        //    return Update<TableName>(updateItem);
        //}

        /// <summary>
        /// 更新由 Table  指定的表的数据
        /// </summary>
        /// <param name="updateItem">由键值队组成的集合，每一个键值队代表一个更新操作，
        /// Key为要更新的内容,类的属性名要和表的列名一致
        /// Value做为 Where 条件的类,类的属性名要和表的列名一致 无条件则为 null，
        /// </param>
        /// <exception cref="System.ArgumentOutOfRangeException" />
        /// <returns>更新的行数</returns>
        //protected virtual int Update<Table>(IDictionary<object, object> updateItem)
        //{
        //    return this.Table.Update<Table>(updateItem);
        //}

        /// <summary>
        /// 更新由 TableName  指定的表的数据
        /// </summary>
        /// <param name="updates">由键值队组成的集合，每一个键值队代表一个更新表的操作，
        /// Key做为 由Linq to sql生成的实体，指示需要操作的表
        /// Value为要更新的数据 {
        ///     由键值队组成的集合，每一个键值队代表一个更新操作，
        ///     Key为要更新的内容 条件的类,类的属性名要和表的列名一致
        ///     Value做为 Where 条件的类,类的属性名要和表的列名一致 无条件则为 null，
        /// }
        /// </param>
        /// <exception cref="System.ArgumentOutOfRangeException" />
        /// <returns>更新的行数</returns>
        protected virtual int Update(IDictionary<Type, NameValue<object, object>> updates)
        {
            return this.Table.Update(updates);
        }

        /// <summary>
        /// 开始一个事务，后操作都将做为一个事务，直到显示调用 RollBack()回滚 或 Commit()提交
        /// </summary>
        public virtual void BeginTransaction()
        {
            Table.BeginTransaction();
        }

        /// <summary>
        /// 回滚事务，必须事先显示的掉用BeginTransaction()
        /// </summary>
        public virtual void CancelTransaction()
        {
            Table.CancelTransaction();
        }

        /// <summary>
        /// 提交事务，必须事先显示的掉用BeginTransaction()
        /// 反回:受影响的行数 -1 数据库错误
        /// </summary>
        /// <param name="count">受影响的行数，如果不等于此预计的行数，则回滚,此参数小于零则不处理受景响的行数</param>
        public virtual int ExecuteTransaction()
        {
            return Table.ExecuteTransaction();
        }

        /// <summary>
        /// 提交事务，如果受影响的行数等于预计的行数。必须事先显示的掉用BeginTransaction()
        /// 反回:受影响的行数 -1 数据库错误，-2 已回滚事务
        /// </summary>
        /// <param name="count">受影响的行数，如果不等于此预计的行数，则回滚,此参数小于零则不处理受景响的行数</param>
        /// <exception cref="System.InvalidOperationException"/>
        /// <returns>更新的行数</returns>
        public int ExecuteTransaction(int count)
        {
            return this.Table.CommitWithCount(count);
        }

        /// <summary>
        /// 日志记录对象
        /// </summary>
        protected static ILog Log = Code.Commen.Log.GetLog("Code.BLL.ManageBase"+typeof(TableName).Name);
    }
}
